<template>
    <div id="bpmnCanvas" style="width:100%;height:500px;"></div>
</template>

<script>

  import BpmnViewer from 'bpmn-js'
  import 'bpmn-js/dist/assets/diagram-js.css'
  import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
  import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
  import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
  import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css'
  import {getAction} from '@/api/manage'
  let bpmnViewer = null

    export default {
        name: "ProcessPicDetail",
        props: {
          procInstId: {
            type: String,
          },
        },
        data(){
          return {
            detailInfo: {},
            highlightModel: {},
            defaultZoom: 1,
            nodeDetail: {},
            scale: 1,
            title: '流程预览',
            showViewDialog: false,
            url: {
              getNodeDetail: '/process/getAuditDetailByTask',
            }
          }
        },
      mounted() {
        this.initPage();
      },
      methods: {
        initPage() {
          bpmnViewer && bpmnViewer.destroy()
          bpmnViewer = new BpmnViewer({
            container: '#bpmnCanvas',
            width: '100%',
          })
          getAction("/process/getFlowInfo", {proInsanceId: this.procInstId}).then(res => {
            if (res.success) {
              this.highlightModel = res.result
              if (bpmnViewer) {
                this.importXml(res.result.xml)
              }
            } else {
              this.$message.warn(res.message);
            }
          })
        },
        getHtmlAttr(source, element, attr) {
          let result = []
          let reg = '<' + element + '[^<>]*?\\s' + attr + '=[\'"]?(.*?)[\'"]?\\s.*?>'
          let matched = source.match(new RegExp(reg, 'gi'))

          matched && matched.forEach(item => {
            item && result.push(item)
          })
          return result
        },
        async importXml(modelXml) {
          // 处理排他网关， 注：流程图预览时，排他网关需要在对应的<bpmndi:BPMNShape>节点上添加属性isMarkerVisible="true"
          let gatewayIds = this.getHtmlAttr(modelXml, 'exclusiveGateway', 'id')
          let modelXmlTemp = modelXml
          if (gatewayIds && gatewayIds.length > 0) {
            gatewayIds.forEach(item => {
              const result = new RegExp('id="(.+?)"').exec(item)
              if (result && result[1]) {
                modelXmlTemp = modelXmlTemp.replace('bpmnElement="' + result[1] + '"', 'bpmnElement="' + result[1] + '" isMarkerVisible="true"')
              }
            })
          }
          const result = await bpmnViewer.importXML(modelXml);
          if (result) {
            this.importXmlSuccess()
          }
        },
        importXmlSuccess() {
          // 使流程图自适应屏幕
          let canvas = bpmnViewer.get('canvas')
          canvas.zoom('fit-viewport', 'auto')
          //设置高亮线和高亮节点,需要配合style中的css样式一起使用，否则没有颜色
          let that = this;
          setTimeout(() => {
            that.setViewerStyle(canvas)
          }, 2000)

          //给任务节点加聚焦和离焦事件
          this.bindEvents()
        },

        setViewerStyle(canvas) {
          //已完成节点高亮
          let executedLightNode = this.highlightModel.highPoint
          if (executedLightNode && executedLightNode.length > 0) {
            executedLightNode.forEach(item => {
              canvas.addMarker(item, 'highlight')
            })
          }

          //顺序线高亮
          let highlightLines = this.highlightModel.highLine
          if (highlightLines && highlightLines.length > 0) {
            highlightLines.forEach(item => {
              canvas.addMarker(item, 'highlightFlow')
            })
          }

          //高亮我执行过的任务
          let highlightIdo = this.highlightModel.ido
          if (highlightLines && highlightLines.length > 0) {
            highlightLines.forEach(item => {
              canvas.addMarker(item, 'highlightIDO')
            })
          }

          //高亮下一个任务
          let toDoHighLightNode = this.highlightModel.waitingToDo
          if (toDoHighLightNode && toDoHighLightNode.length > 0) {
            toDoHighLightNode.forEach((item, index) => {
              canvas.addMarker(item, 'highlightTODO')
            })
            /* document.querySelectorAll('.highlight').forEach((item,index)=>{
               item.querySelector('.djs-visual rect').setAttribute('stroke-dasharray', '4,4')
             })*/
          }
          this.$forceUpdate();
        },

        // 以下代码为：为节点注册鼠标悬浮事件
        bindEvents() {
          let eventBus = bpmnViewer.get('eventBus')
          let overlays = bpmnViewer.get('overlays');
          eventBus.on('element.hover', (e) => {
            if (e.element.type === 'bpmn:UserTask') {
              if (this.nodeDetail[e.element.id]) {
                if (e.element.type === "bpmn:UserTask") {
                  this.detailInfo = this.nodeDetail[e.element.id]
                  this.genNodeDetailBox(e, overlays);
                }
                this.detailInfo = this.nodeDetail[e.element.id]
              } else {
                getAction(this.url.getNodeDetail, {
                  proInsanceId: this.procInstId,
                  taskId: e.element.id
                }).then(res => {
                  if (res.success) {
                    if (e.element.type === "bpmn:UserTask") {
                      this.nodeDetail[e.element.id] = res.result;
                      this.detailInfo = res.result
                      this.genNodeDetailBox(e, overlays);
                    }
                  }
                })
              }
            }
          })
          eventBus.on('element.out', (e) => {
            if (e.element.type === 'bpmn:UserTask') {
              this.detailInfo = {}
              overlays.clear();
            }
          })
        },

        //悬浮框设置
        genNodeDetailBox(e, overlays) {
          overlays.add(e.element.id, {
            position: {bottom: e.element.height, left: 0},
            html: `
              <div class="tipBox" >
                <p>节点名称：${this.detailInfo.taskName || ""}</p>
                <p>审批人员：${this.detailInfo.assign || ""}</p>
                <p>节点状态：${this.detailInfo.completeStatus === 'completed' ? '完成' : '未完成'}</p>
                <p>开始时间：${this.detailInfo.startTime || ""}</p>
                <p>结束时间：${this.detailInfo.endTime || ""}</p>
                <p>审批耗时：${this.detailInfo.duration || ""}</p>
             </div>`
          })
        },
      },
      /*watch:{
        procInstId(newVal, oldVal) {
          if(newVal){
            this.initPage()
          }
        },
      }*/
    }
</script>

<style>


  /*.bjs-powered-by {
      display: none;
  }*/
  .flowMsgPopover {
    display: none;
  }

  .highlight .djs-visual > :nth-child(1) {
    stroke: green !important;
    fill: rgba(0, 80, 0, 0.4) !important;
  }

  .highlightFlow .djs-visual > :nth-child(1) {
    stroke: green !important;
  }

  .highlightIDO .djs-visual > :nth-child(1) {
    stroke: rgb(255, 196, 0) !important;
    fill: rgba(255, 196, 0, 0.4) !important;
  }

  .highlightTODO .djs-visual > :nth-child(1) {
    stroke: rgb(255, 0, 0) !important;
    fill: rgba(255, 255, 255, 0.4) !important;
  }

  @-webkit-keyframes dynamicNode {
    to {
      stroke-dashoffset: 100%;
    }
  }

  .tipBox {
    width: 300px;
    background: #fff;
    border-radius: 4px;
    border: 1px solid #ebeef5;
    padding: 12px;
    border-radius: 8px;
    box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);


  /*.ant-popover-arrow{
      display: none;
  }*/
  p {
    line-height: 28px;
    margin: 0;
    padding: 0;
  }

  }

</style>